/*
 通信管理模块
 */
#include <algorithm>
#include <winsock2.h>
#include "communicate_mgr.h"
#include "../base/sys_config.h"
#pragma comment(lib,"ws2_32.lib")

CommunicateMgr::CommunicateMgr() {

}

CommunicateMgr::~CommunicateMgr() {

}

bool CommunicateMgr::startServer() {
    // 1. 创建服务器socket
    // 2. 创建工作线程 this
	_taskProcHandle = CreateThread(NULL, 0, TaskThreadProc, this, 0, NULL);
	return true;
}

bool CommunicateMgr::stopServer() {
    // 关闭工作线程
    _isRunProc = false;
    WaitForSingleObject(_taskProcHandle, INFINITE);
    CloseHandle(_taskProcHandle);
	return true;
}

void CommunicateMgr::unregisterNotify(CommunicateNotify *notify) {
	_notifyInterface = NULL;
}

AsyncEvt CommunicateMgr::doAsyncSelect() {
    int timeOutMs = SysConfig::getInst()->getAsyncTimeOutMs();
    struct timeval tv;
    tv.tv_sec = timeOutMs / 1000;
    tv.tv_usec = timeOutMs%100*1000;

    FD_ZERO(&_rfds);
    FD_SET(_serverSock, &_rfds);
    int maxfd = _serverSock;

    std::vector<DevClientInfo>::iterator it = _devCLientInfoList.begin();
    for ( ; it != _devCLientInfoList.end(); ++it ) {
        FD_SET(it->sock, &_rfds);
        maxfd = maxfd > it->sock ? maxfd : it->sock;
    }

    int ret = select(maxfd + 1, &_rfds, NULL, NULL, &tv);
    AsyncEvt evt = EVT_NONE;
    if ( ret == -1 ) {
        evt = EVT_SOCK_ERR;
    }
    else if ( ret == 0 ) {
        evt = EVT_TIMEOUT;
    }
    else {
		// 优先处理客户端连接请求
        if ( FD_ISSET(_serverSock, &_rfds) ) {
            evt = EVT_NEW_CLIENT;
        }
        else {
            evt = EVT_DATA_COMMING;
        }
    }
    return evt;
}

void CommunicateMgr::onAcceptNewClient() {
	struct sockaddr_in cleintAddr;
	int size = sizeof(cleintAddr);
	int clientSock = accept(_serverSock, (struct sockaddr*)&cleintAddr, &size);
	// setNonBlock(clnt_sock, true);//将客户端设置为非阻塞
	if (_devCLientInfoList.size() > SysConfig::getInst()->getMaxDevCnt()) {
		return;
	}
	_devCLientInfoList.push_back(DevClientInfo(clientSock, -1, false));
}

void CommunicateMgr::onRecvClientData() {
	unsigned char buffer[1024] = { 0 };
	std::vector<DevClientInfo>::iterator it = _devCLientInfoList.begin();
	
	while ( it != _devCLientInfoList.end() ) {
		if ( !FD_ISSET(it->sock, &_rfds) ) {
			continue;
		}
		if (!it->hasAuthed) {
			int dataBufferId = -1;
			if (_notifyInterface != NULL) {
				int size = recv(it->sock, (char *)buffer, 1024, 0);
				dataBufferId = _notifyInterface->onDevAuth(buffer, size);
			}

			// 鉴权失败
			if (dataBufferId == -1 ) {
				closesocket(it->sock);
				it = _devCLientInfoList.erase(it);
			}
			else {
				it->dataBufferId = dataBufferId;
				it->hasAuthed = true;
			}
		}
		else {
			int size = recv(it->sock, (char *)buffer, 1024, 0);
			_notifyInterface->onRecvData(it->dataBufferId, buffer, size);
			++it;
		}
	}
}

DWORD CommunicateMgr::TaskThreadProc(PVOID arg) {
    CommunicateMgr *thisPtr = (CommunicateMgr *)arg;
    while ( thisPtr->_isRunProc ) {
        AsyncEvt evt = thisPtr->doAsyncSelect();

        switch(evt) {
        case EVT_SOCK_ERR:
            break;

        case EVT_NEW_CLIENT:
			thisPtr->onAcceptNewClient();
            break;

        case EVT_DATA_COMMING:
			thisPtr->onRecvClientData();
            break;

        case EVT_TIMEOUT:
            break;
        }
    }
    return 0;
}